#include <string.h>
#include "sipsiparser.h"
#include "buildersectioncontrol.h"
#include "pluginbat.h"
#include "builderplugin.h"
#include "plugindvbfun.h"
#include "dtmbfreqtable.h"

typedef enum
{
	PLUGIN_FULL_STATUS_IDLE,
	PLUGIN_FULL_STATUS_WAIT_LOCK,
	PLUGIN_FULL_STATUS_RECV_SIPSI,
	PLUGIN_FULL_STATUS_RECV_BAT,
}PLUGIN_FULL_STATUS_T;

typedef struct
{
	PLUGIN_FULL_STATUS_T			m_eStatus;
	//bat
	unsigned int						m_u32BatRecved;
	builder_bat_control_t				m_stBatRecvCtrl;
	
	builder_tuner_t					m_stCurTuner;
	unsigned int						m_u32Process;
	builder_section_control_t			m_stSecCtrl;
	unsigned int						m_u32DataOK;
	builder_tuner_t					m_stDataOkTunerInfo;
	unsigned int						m_u32TimeOut;
	
	builder_tuner_t*					m_pstTunerList;
	unsigned int						m_u32StartIndex;
	unsigned int						m_u32EndIndex;
	unsigned int						m_u32Index;
}builder_full_search_t;

builder_full_search_t pstFullCtrl = {PLUGIN_FULL_STATUS_IDLE};


int PluginFullSearchReset()
{
	int s32Ret = -1;
	
	PluginDvbLogcat("PluginFullSearchReset() - entry\r\n");	
	
	pstFullCtrl.m_eStatus = PLUGIN_FULL_STATUS_IDLE;
	pstFullCtrl.m_u32DataOK = 0;
	pstFullCtrl.m_u32Process = 0;
	pstFullCtrl.m_u32TimeOut = 0;
	
	pstFullCtrl.m_u32BatRecved = 0;
	PluginBatStop(&pstFullCtrl.m_stBatRecvCtrl);

	s32Ret = PluginSectionDataStop(&pstFullCtrl.m_stSecCtrl);
	PluginDvbLogcat("PluginFullSearchReset() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;		
}

int PluginFullSearchStart(builder_all_search_t* pstParam)
{
	int s32Ret = -1;
	unsigned int u32FreqCnt;
	unsigned int i;
	
	PluginDvbLogcat("PluginFullSearchStart() - entry\r\n");
	if(pstParam)
	{
		u32FreqCnt = 0;
		pstFullCtrl.m_u32BatRecved = 0;
		pstFullCtrl.m_pstTunerList = PluginGetFreqTable(&u32FreqCnt);
		s32Ret = PluginCheckTunerInfo(&pstParam->m_stStartTunerInfo);
		if(s32Ret == 0)
		{
			s32Ret = PluginCheckTunerInfo(&pstParam->m_stEndTunerInfo);
			if(s32Ret == 0)
			{
				if(pstParam->m_stStartTunerInfo.m_u32Freq < pstParam->m_stEndTunerInfo.m_u32Freq)
				{
					i = 0;
					while(pstFullCtrl.m_pstTunerList[i].m_u32Freq < pstParam->m_stStartTunerInfo.m_u32Freq)
						i++;
					if(pstFullCtrl.m_pstTunerList[i].m_u32Freq == pstParam->m_stStartTunerInfo.m_u32Freq)
						pstFullCtrl.m_u32StartIndex = i;
					else
						pstFullCtrl.m_u32StartIndex = i + 1;

					i++;
					while(pstFullCtrl.m_pstTunerList[i].m_u32Freq < pstParam->m_stEndTunerInfo.m_u32Freq)
						i++;
					pstFullCtrl.m_u32EndIndex = i;

					pstFullCtrl.m_u32Index = pstFullCtrl.m_u32StartIndex;
					memcpy(&pstFullCtrl.m_stCurTuner, &pstFullCtrl.m_pstTunerList[pstFullCtrl.m_u32StartIndex], sizeof(builder_tuner_t));
					s32Ret = PluginDvbTunerLock(&pstFullCtrl.m_stCurTuner);
					pstFullCtrl.m_eStatus = PLUGIN_FULL_STATUS_WAIT_LOCK;
					pstFullCtrl.m_u32TimeOut = 2;
				}
				else
				{
					s32Ret = -1;
					PluginDvbLogcat("PluginFullSearchStart() - start freq = %d < end freq = %d\r\n", pstParam->m_stStartTunerInfo.m_u32Freq, pstParam->m_stEndTunerInfo.m_u32Freq);
				}
			}
		}
	}
	PluginDvbLogcat("PluginFullSearchStart() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;		
}

int PluginFullSearchTick()
{
	int s32Ret = -1;
	
	PluginDvbLogcat("PluginFullSearchTick() - entry\r\n");
	if(pstFullCtrl.m_eStatus == PLUGIN_FULL_STATUS_RECV_SIPSI)
	{
		s32Ret = PluginSectionDataTick(&pstFullCtrl.m_stSecCtrl);
		if(s32Ret != 0)
		{
			if (1 == s32Ret)
			{
				pstFullCtrl.m_u32DataOK = 1;
				memcpy(&pstFullCtrl.m_stDataOkTunerInfo, &pstFullCtrl.m_stCurTuner, sizeof(builder_tuner_t));
				s32Ret = 0;
			}
			else 
			{
				pstFullCtrl.m_u32DataOK = 0;
				s32Ret = PluginSectionDataStop(&pstFullCtrl.m_stSecCtrl);
				if(s32Ret != 0)
					PluginDvbLogcat("PluginFullSearchTick() -PluginSectionDataStop error\r\n");
			}
			
			pstFullCtrl.m_u32Index++;
			pstFullCtrl.m_u32Process = (pstFullCtrl.m_u32Index-pstFullCtrl.m_u32StartIndex)*100/(pstFullCtrl.m_u32EndIndex - pstFullCtrl.m_u32StartIndex +1);
			if(pstFullCtrl.m_u32Index <= pstFullCtrl.m_u32EndIndex)
			{
				memcpy(&pstFullCtrl.m_stCurTuner, &pstFullCtrl.m_pstTunerList[pstFullCtrl.m_u32Index], sizeof(builder_tuner_t));
				PluginDvbLogcat("PluginFullSearchTick() - start next freq stBuilderCtrl.m_stCurTuner.m_u32Freq = %d\r\n", pstFullCtrl.m_stCurTuner.m_u32Freq);
				s32Ret = PluginDvbTunerLock(&pstFullCtrl.m_stCurTuner);
				pstFullCtrl.m_eStatus = PLUGIN_FULL_STATUS_WAIT_LOCK;	
			}
			else
			{
				PluginDvbLogcat("PluginFullSearchTick() - all freq index end [%d~%d]\r\n", pstFullCtrl.m_u32StartIndex, pstFullCtrl.m_u32EndIndex);
				pstFullCtrl.m_u32Process = SCAN_ALL_PROCESS;
			}
		}
	}
	else if(pstFullCtrl.m_eStatus == PLUGIN_FULL_STATUS_RECV_BAT)
	{
		s32Ret = PluginBatTick(&pstFullCtrl.m_stBatRecvCtrl);
		if(s32Ret != 0)
		{
			pstFullCtrl.m_u32DataOK = 1;//recv pat pmt end then recv bat
			s32Ret = 0;
			PluginBatStop(&pstFullCtrl.m_stBatRecvCtrl);
			pstFullCtrl.m_u32BatRecved = 0;

			//next freq
			pstFullCtrl.m_u32Index++;
			pstFullCtrl.m_u32Process = (pstFullCtrl.m_u32Index-pstFullCtrl.m_u32StartIndex)*100/(pstFullCtrl.m_u32EndIndex - pstFullCtrl.m_u32StartIndex +1);
			if(pstFullCtrl.m_u32Index <= pstFullCtrl.m_u32EndIndex)
			{
				memcpy(&pstFullCtrl.m_stCurTuner, &pstFullCtrl.m_pstTunerList[pstFullCtrl.m_u32Index], sizeof(builder_tuner_t));
				PluginDvbLogcat("PluginFullSearchTick() - start next freq stBuilderCtrl.m_stCurTuner.m_u32Freq = %d\r\n", pstFullCtrl.m_stCurTuner.m_u32Freq);
				s32Ret = PluginDvbTunerLock(&pstFullCtrl.m_stCurTuner);
				pstFullCtrl.m_eStatus = PLUGIN_FULL_STATUS_WAIT_LOCK;	
			}
			else
			{
				PluginDvbLogcat("PluginFullSearchTick() - all freq index end [%d~%d]\r\n", pstFullCtrl.m_u32StartIndex, pstFullCtrl.m_u32EndIndex);
				pstFullCtrl.m_u32Process = SCAN_ALL_PROCESS;
			}
		}
	}

	PluginDvbLogcat("PluginFullSearchTick() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;		
}

int PluginFullSearchLockFinish(builder_tuner_t* pstTunerInfo, unsigned int u32Lock)
{
	int s32Ret = -1;
	
	PluginDvbLogcat("PluginFullSearchLockFinish() - entry, pstTunerInfo = %p, u32Lock = %d\r\n", pstTunerInfo, u32Lock);
	if(pstTunerInfo && pstFullCtrl.m_eStatus==PLUGIN_FULL_STATUS_WAIT_LOCK)
	{
		if(u32Lock == 1)
		{
			builder_section_control_cfg_t stCfg;
			stCfg.m_eSecRecvCfg = BUILDER_SECTION_DATA_NOSDT_CONTINUE;
			stCfg.m_u16PSITimeoutRatio = 9;
			stCfg.m_u16SITimeoutRatio = 2;

			PluginSectionDataSetConfig(&pstFullCtrl.m_stSecCtrl, &stCfg);
			s32Ret = PluginSectionDataReset(&pstFullCtrl.m_stSecCtrl);
			if(s32Ret == 0)
			{
				pstFullCtrl.m_u32TimeOut = 4;
				s32Ret = PluginSectionDataStart(&pstFullCtrl.m_stSecCtrl);
				pstFullCtrl.m_u32Process = (pstFullCtrl.m_u32Index-pstFullCtrl.m_u32StartIndex)*100/(pstFullCtrl.m_u32EndIndex - pstFullCtrl.m_u32StartIndex +1);
				pstFullCtrl.m_eStatus = PLUGIN_FULL_STATUS_RECV_SIPSI;
				memcpy(&pstFullCtrl.m_stDataOkTunerInfo, &pstFullCtrl.m_stCurTuner, sizeof(pstFullCtrl.m_stDataOkTunerInfo));
			}
			else
			{
				pstFullCtrl.m_eStatus = PLUGIN_FULL_STATUS_IDLE;
				PluginDvbLogcat("PluginFullSearchLockFinish() - start recv sdt error\r\n");
			}
		}
		else
		{
			pstFullCtrl.m_u32DataOK = 0;
			pstFullCtrl.m_u32Index++;
			pstFullCtrl.m_u32Process = (pstFullCtrl.m_u32Index-pstFullCtrl.m_u32StartIndex)*100/(pstFullCtrl.m_u32EndIndex - pstFullCtrl.m_u32StartIndex +1);
			
			if(pstFullCtrl.m_u32Index <= pstFullCtrl.m_u32EndIndex)
			{
				PluginSectionDataReset(&pstFullCtrl.m_stSecCtrl);
				memcpy(&pstFullCtrl.m_stCurTuner, &pstFullCtrl.m_pstTunerList[pstFullCtrl.m_u32Index], sizeof(builder_tuner_t));
				PluginDvbLogcat("PluginFullSearchLockFinish() - start next freq stBuilderCtrl.m_stCurTuner.m_u32Freq = %d\r\n", pstFullCtrl.m_stCurTuner.m_u32Freq);
				s32Ret = PluginDvbTunerLock(&pstFullCtrl.m_stCurTuner);
				pstFullCtrl.m_eStatus = PLUGIN_FULL_STATUS_WAIT_LOCK;	
			}
			else
			{
				PluginDvbLogcat("PluginFullSearchLockFinish() - all freq index end [%d~%d]\r\n", pstFullCtrl.m_u32StartIndex, pstFullCtrl.m_u32EndIndex);
				s32Ret = 0;
				pstFullCtrl.m_u32Process = SCAN_ALL_PROCESS;
				pstFullCtrl.m_eStatus = PLUGIN_FULL_STATUS_IDLE;	
			}
		}
	}
	else
	{
		PluginDvbLogcat("PluginFullSearchLockFinish() - receive error message\r\n");
		s32Ret = -1;
	}
	PluginDvbLogcat("PluginFullSearchLockFinish() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}

int PluginFullSearchHandleDataRecved(unsigned char* pu8Data, unsigned int hFilter)
{
	int s32Ret = -1;
	unsigned int u32Process;

	PluginDvbLogcat("PluginFullSearchHandleDataRecved() - entry, pu8Data = %p, hFilter = %x\r\n", pu8Data, hFilter);
	if(pu8Data && pstFullCtrl.m_eStatus==PLUGIN_FULL_STATUS_RECV_SIPSI)
	{
		s32Ret = PluginSectionDataRecv(&pstFullCtrl.m_stSecCtrl, hFilter, pu8Data);
		if(s32Ret == 0)
		{
			s32Ret = PluginSectionDataGetProcess(&pstFullCtrl.m_stSecCtrl, &u32Process);
			if(s32Ret == 0)
			{
				pstFullCtrl.m_u32Process = (pstFullCtrl.m_u32Index-pstFullCtrl.m_u32StartIndex)*100/(pstFullCtrl.m_u32EndIndex - pstFullCtrl.m_u32StartIndex +1);
				pstFullCtrl.m_u32Process += u32Process/(pstFullCtrl.m_u32EndIndex - pstFullCtrl.m_u32StartIndex +1);

				if(u32Process == 100 && pstFullCtrl.m_u32BatRecved==0)
				{
					PluginBatReset(&pstFullCtrl.m_stBatRecvCtrl);
					s32Ret = PluginBatStart(&pstFullCtrl.m_stBatRecvCtrl);
					pstFullCtrl.m_eStatus = PLUGIN_FULL_STATUS_RECV_BAT;
					pstFullCtrl.m_u32TimeOut = 0;
				}
				else if(u32Process == 100)
				{
					pstFullCtrl.m_u32DataOK = 1;
					pstFullCtrl.m_u32Index++;
					memcpy(&pstFullCtrl.m_stDataOkTunerInfo, &pstFullCtrl.m_stCurTuner, sizeof(builder_tuner_t));
					if(pstFullCtrl.m_u32Index <= pstFullCtrl.m_u32EndIndex)
					{
						memcpy(&pstFullCtrl.m_stCurTuner, &pstFullCtrl.m_pstTunerList[pstFullCtrl.m_u32Index], sizeof(builder_tuner_t));
						PluginDvbLogcat("PluginFullSearchHandleDataRecved() - start next freq stBuilderCtrl.m_stCurTuner.m_u32Freq = %d\r\n", pstFullCtrl.m_stCurTuner.m_u32Freq);
						s32Ret = PluginDvbTunerLock(&pstFullCtrl.m_stCurTuner);
						pstFullCtrl.m_eStatus = PLUGIN_FULL_STATUS_WAIT_LOCK;	
					}
					else
					{
						PluginDvbLogcat("PluginFullSearchHandleDataRecved() - all freq index end [%d~%d]\r\n", pstFullCtrl.m_u32StartIndex, pstFullCtrl.m_u32EndIndex);
						pstFullCtrl.m_u32Process = SCAN_ALL_PROCESS;
					}
				}
			}
			else
			{
				PluginDvbLogcat("PluginFullSearchHandleDataRecved() - get section control process not OK\r\n");
			}
		}
		else
		{
			PluginDvbLogcat("PluginFullSearchHandleDataRecved() - send to section control not OK\r\n");
			s32Ret = 0;
		}
	}
	else if(pu8Data && pstFullCtrl.m_eStatus==PLUGIN_FULL_STATUS_RECV_BAT)
	{
		s32Ret = PluginBatRecv(&pstFullCtrl.m_stBatRecvCtrl, hFilter, pu8Data);
		if(s32Ret == 0)
		{
			PluginBatGetProcess(&pstFullCtrl.m_stBatRecvCtrl, &u32Process);
			if(u32Process == 100)
			{
				pstFullCtrl.m_u32DataOK = 1;
				pstFullCtrl.m_u32Index++;
				memcpy(&pstFullCtrl.m_stDataOkTunerInfo, &pstFullCtrl.m_stCurTuner, sizeof(builder_tuner_t));
				if(pstFullCtrl.m_u32Index <= pstFullCtrl.m_u32EndIndex)
				{
					memcpy(&pstFullCtrl.m_stCurTuner, &pstFullCtrl.m_pstTunerList[pstFullCtrl.m_u32Index], sizeof(builder_tuner_t));
					PluginDvbLogcat("PluginFullSearchHandleDataRecved() - start next freq stBuilderCtrl.m_stCurTuner.m_u32Freq = %d\r\n", pstFullCtrl.m_stCurTuner.m_u32Freq);
					s32Ret = PluginDvbTunerLock(&pstFullCtrl.m_stCurTuner);
					pstFullCtrl.m_eStatus = PLUGIN_FULL_STATUS_WAIT_LOCK;	
				}
				else
				{
					PluginDvbLogcat("PluginFullSearchHandleDataRecved() - all freq index end [%d~%d]\r\n", pstFullCtrl.m_u32StartIndex, pstFullCtrl.m_u32EndIndex);
					pstFullCtrl.m_u32Process = SCAN_ALL_PROCESS;
				}
			}
		}
	}

	PluginDvbLogcat("PluginFullSearchHandleDataRecved() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;
}


int PluginFullGetSearchData(builder_ts_t* pstTs, builder_service_t* pstServices, unsigned int* pu32ServiceCnt, builder_section_t** ppstBat, builder_section_t** ppstNit)
{
	int s32Ret = -1;
	builder_ts_t stTs;
	builder_service_t astServices[BUILDER_MAX_PROG_PER_TS];
	unsigned int u32ServiceCnt = 0;
	
	PluginDvbLogcat("PluginFullGetSearchData() - entry, pstTs = %p, pstServices = %p, pu32ServiceCnt = %p, pstBat = %p, pstNit = %p\r\n", pstTs, pstServices, pu32ServiceCnt, ppstBat, ppstNit);
	if(pstFullCtrl.m_u32DataOK == 1)
	{
		memset(&stTs, 0, sizeof(stTs));
		s32Ret = PluginSectionDataGetSections(&pstFullCtrl.m_stSecCtrl, &stTs.m_stSiPsi);
		if(s32Ret == 0)
		{
			if(stTs.m_stSiPsi.m_pstPat && stTs.m_stSiPsi.m_pstPmt)
			{
				memcpy(&stTs.m_stTuner, &pstFullCtrl.m_stDataOkTunerInfo, sizeof(stTs.m_stTuner));
				s32Ret = PluginParseTs(&stTs, astServices, &u32ServiceCnt);
				if(s32Ret == 0)
				{
					memcpy(pstTs, &stTs, sizeof(stTs));
					*pu32ServiceCnt = u32ServiceCnt;
					memcpy(pstServices, astServices, u32ServiceCnt*sizeof(builder_service_t));
				}
				else
					PluginDvbLogcat("PluginFullGetSearchData() - PluginParseTs error\r\n");
			}
		}
		
		*ppstBat = NULL;
		PluginBatGetSections(&pstFullCtrl.m_stBatRecvCtrl, ppstBat);
		
		pstFullCtrl.m_u32DataOK = 0;
	}
	PluginDvbLogcat("PluginFullGetSearchData() - return, s32Ret = %d\r\n", s32Ret);
	return s32Ret;	
}

int PluginFullGetProcess(unsigned int* pu32DataOk, unsigned int* pu32Process)
{
	int s32Ret = -1;
	
	PluginDvbLogcat("PluginFullGetProcess() - entry, pu32DataOk = %p, pu32Process = %p\r\n", pu32DataOk, pu32Process);
	if(pu32DataOk && pu32Process)
	{
		*pu32DataOk = pstFullCtrl.m_u32DataOK;
		*pu32Process = pstFullCtrl.m_u32Process;
		if(*pu32Process == SCAN_ALL_PROCESS)
			pstFullCtrl.m_eStatus = PLUGIN_FULL_STATUS_IDLE;
		s32Ret = 0;
	}
	PluginDvbLogcat("PluginFullGetProcess() - return, s32Ret = %d\r\n", s32Ret);
	
	return s32Ret;	
}

